Module# 02: Generic Programming                      Lecture#04: Parameterized Generic Classes

 

// Example 4.1: A generic method in a generic class can be declared as static

 

class GenericStaticDemo  {

    // Defining a static generic method to print any data type

     static void gPrint (T t)  {

          System.out.println (t);

    }

  

    public static void main(String[] args)    {

        gPrint(101);              // Calling generic method with Integer argument  

       

        gPrint("Joy with Java"); // Calling generic method with String argument

  

        gPrint(3.1412343);       // Calling generic method with double argument

    }

}

 

// Example 4.2: A generic method or nay method in a class can be declared as static method

 

class GenericClass<T>  {      // Use < > to specify class type

    T obj;                    // An object of type T is declared

    GenericClass(T obj) {     // Constructor of the generic class

        this.obj = obj; 

    } 

    public void static print(T obj)  {   // A method in the class

        System.out.println(obj);

    }

}

 

class GenericStaticDemo2 {

     public void static main(String args a[]) {

          GenericClass<Integer> a = new GenericClass<Integer>(new Integer x[ ] {10, 20, 30, 40, 50});

   

          GenericClass<String> s = new GenericClass<String>("Joy with Java");

           

          GenericClass<Double> d = new GenericClass<Double>(1.23);

   

          // Printing the data ...

          print(a);          // Printing the array a

          print(s);          // Printing the string

          print(d);          // Printing the value

    }

}

 

// Example 4.3: A generic class should be declared with class type only; not with primitive data types

 

class GenericClass<T>  {      // Use < > to specify class type

    T obj;                    // An object of type T is declared

    GenericClass(T obj) {     // Constructor of the generic class

        this.obj = obj; 

    } 

}

class GenericClassDemo3 {

     public void static main(String args a[]) {

          GenericClass<Integer> a = new GenericClass<Integer>(123);  // Okay

          GenericClass<int> a = new GenericClass<int>(234);          // ERROR!

          GenericClass<String> s = new GenericClass<String>("Joy with Java"); // Okay

          GenericClass<double> d = new GenericClass<double>(9.87); // ERROR!

          GenericClass<Double> d = new GenericClass<Double>(1.23); // Okay

   

    }

}

 

// Example 4.4: A generic class with multiple type parameters

 

class GenericClass<T, V>  {      // Use < > to specify class type

    T obj1;                      // An object of type T is declared

    V obj2;                      // An object of type V is declared

    // Constructor of the generic class

    GenericClass(T obj1, V obj2) {

        this.obj1 = obj1;

        this.obj2 = obj2; 

    } 

}

 

// Example 4.5: Generic class with two parameters

 

class GC2<T1, T2>  {

    T1 obj1;     // An object of type T1

    T2 obj2;     // An object of type T2

 

    GC2(T1 obj1, T2 obj2)     {   // Constructor

        this.obj1 = obj1;

        this.obj2 = obj2;

    }

   public void print()  { // A local method in GC2

        System.out.println(obj1);

        System.out.println(obj2);

    }

}

 

class GC2Test { // Driver class using GC2

    public static void main (String[] args)  {

        GC2 <String, Integer> obj1 = new GC2<String, Integer>("GC", 9);

        obj1.print();

        GC2 <Integer, Double> obj2 = new GC2<Integer, Double>(123, 1.2);

        obj2.print();

    }

}

 

 

 // Example 4.6: Another example of a generic class with multiple parameters

 

public class PairData <T, V> {

      // Two fields of generic type T and V

       private T x;

       private V y;        // Note: How a field can be defined generically.

 

    // Constructor

       public PairData(T a, V b) {

                 x = a;

                 y = b;

      }

 

       // Get the T-type value for a pair-data

       public T getTvalue() {

           return x;

      }

 

       // Get the V-type value for a pair-data

       public V getVvalue() {

           return y;

      }

 

     // To print the data member in an object

      public void printData() {

              System.out.println (getTvalue +,” getVvalue);

     }

}  // This completes the definition of the class PairData<T, V>

 

// The driver class is programmed below.

 class  MultiParamtereGenericClassTest {

       public static void main( String args[] ) { 

            // A pair data with both members as String

            PairData<String, String> a = new PairData<String, String> (“Debasis”, “Samanta”);

            a.printData();

            // A pair data with the first member as String and other as Integer

            PairData<String, Integer> b = new PairData<String, Integer> (“Debasis”, 789);

            b.printData();

 

            // A pair data with the first member as Integer and other as String

            PairData<Integer, String> c = new PairData<Integer, String> (943, “Samanta”);

            c.printData();

 

            // A pair data with the first member as Integer and other as Double

            PairData<Integer, Double> d = new PairData<Integer, Double> (555, 12.34);

            d.printData();

      }

}

 

// Example 4.7: Generic class with method overloading

 

// Define the user defined Student class

class Student {

   String name;   // Name of the students

   int marks[3];   // Stores the marks in three subjects

            

   // Constructor for the class Student

   Student(String s, int m[ ]) {

       name = s;

       marks = m;

   }

 

   //Defining a method to print student’s record

    void printStudent() {

        System.out.println(“Name :+ name);     

        System.out.println(“Scores :+ marks[0] +  + marks[1] +  + marks[2] );     

    }

 }     // End of the class Student

 

// Defining a generic array with two type parameters

 class GenericMultiArrays<T, S> {

      //Declaring an array, which should store any type T of data

      T a[ ];    // Define that the array a[ ] can store one type of data

      S b[];     // Define that the array b[ ] can store another type of data

      GenericArrays(T x, S y) {        // Define a constructor

          a = x;

          b = y;

      }

 

      T getDataT(int i) {// To return the element stored in i-th place in the array

      return a[i];

      }

 

      S getDataS(int i) { //To return the element stored in i-th place in the array

           return b[i];

      }

 

// Overloaded methods in the generic class

      void printData (T t) {       // A generic method to print the elements in array t

           for(int i = 0; i < t.length(); i ++)

                 System.out.print(t.getData(i) +  ); //Print the i-th element in t

           System.out.println();      // Print a new line

      }

  

      void printData(S s){       //An overloaded generic method to print elements in s

          for(int i = 0; i < s.length(); i ++)

               s[i].printStudent()        // Print the i-th student in s

          System.out.println();          // Print a new line

      }

 

// Few additional methods

      void reverseArray(T t) {    //Generic method to reverse the order of elements in t

          int front = 0, rear = t.length-1; T temp;

          while( front < rear)  {

                temp = t[rear];

               t[rear] = t[front];

               t[front] = temp;

               front++; rear--;

          }

      }

      void reverseArray(S s){//Generic method to reverse the order of elements in s

      int front = 0, rear = s.length-1; S temp;

      while( front < rear)  {

           temp = s[rear]

           s[rear] = s[front];

           s[front] = temp;

           front++; rear--;

      }

   }

}      // End of the definition of class GenericMultiArrays

 

// Driver class is programmed below

      Class GenericMultiArraysDemo {

           public void static main(String args a[]) {

        //Creating an array of String data

        String t[ ] = {“A”, “B”, “C”};      // It is an array of String data

 

       //Creating an array of Students’ data

        Student s[3];     // It is an array of String data

        s[0] = new Student(“Ram”, 86, 66, 96);

        s[1] = new Student(“Rahim”, 88, 99, 77);

        s[2] = new Student(“John”, 75, 85, 95);

 

       // Store the data into generic arrays

       GenericArrays<String, Student> arrayData = new GenericArrays<String,

                                                             Student>(t, s);

 

// Printing the data ...

       arrayData.printData(t);          // Printing the array of strings

 

       //Reverse ordering of data ...

       arrayData.reverseArray(t);

 

       // Printing the data ...

       arrayData.printData(s);          // Printing the student’s data

 

       //Reverse ordering of data ...

       arrayData.reverseArray(s);

 

       // Printing the data after reverse ordering ...

       arrayData.printData(t);          // Printing the array of strings

 

       arrayData.printData(s);          // Printing the array of students

   }

}

 

// Example 4.8: A generic class definition with compile-time error

 

GenericError<T> {

    T[ ] array;    // an array of type T

      

    // Pass the constructor a reference to  an array of type T.

    GenericError (T[ ] t) {

        array = t;

    }

 

    double average() {   // Return type double in all cases

        double sum = 0.0;

        for(int i=0; i < array.length; i++)

            sum += array[i].doubleValue();      // Here is a compiler error!

        return sum / array.length;

    }

}